﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using Hxsoft.AppV1;

namespace Hxsoft.AppV1.Module
{
	/// <summary>
	/// 专题导航类型。
	/// </summary>
	[Serializable]
	public enum SpecialNavigationType
	{
		/// <summary>
		/// 页面导航。
		/// </summary>
		Page = 0,
		/// <summary>
		/// 模块导航。
		/// </summary>
		Module,
		/// <summary>
		/// 自定义导航。
		/// </summary>
		Custom,
	}

	/// <summary>
	/// 专题导航项。
	/// </summary>
	[Serializable]
	public class SpecialNavigationItem
	{
		/// <summary>
		/// 导航名称。
		/// </summary>
		public string Name { get; set; }
		/// <summary>
		/// 导航类别。
		/// </summary>
		public SpecialNavigationType Type { get; set; }
		/// <summary>
		/// 导航值。
		/// </summary>
		public string Value { get; set; }
	}



	public partial class Special : ICreator
	{
		/// <summary>
		/// 主导航对象。
		/// </summary>
		public List<SpecialNavigationItem> MainNavigationObject
		{
			get
			{
				if (string.IsNullOrEmpty(MainNavigation))
					return null;
				return Serialization.DeserializeJson<List<SpecialNavigationItem>>(MainNavigation);
			}
			set
			{
				if (value == null)
					MainNavigation = null;
				MainNavigation = Serialization.SerializeJson(value);
			}
		}
	}



	/// <summary>
	/// Specials 类。
	/// </summary>
	public static partial class Specials
	{
		public const string INFO_TYPE = "Special";
		public const string SpecialClassDicClassCode = "SpecialClass";



		#region GetIdentifier
		/// <summary>
		/// 根据指定的信息获取专题标识。
		/// </summary>
		/// <param name="o">资源的集合。</param>
		/// <param name="siteId">所属站点标识。</param>
		/// <param name="specialCode">专题代码。</param>
		/// <returns>指定的专题标识。</returns>
		internal static int? GetIdentifier(this System.Data.Linq.Table<Special> o, int siteId, string specialCode)
		{
			return (from p in o
				   where p.SiteId == siteId && p.SpecialCode == specialCode
				   select (int?)p.SpecialId).SingleOrDefault();
		}

		/// <summary>
		/// 根据指定的信息获取专题标识。
		/// </summary>
		/// <param name="siteId">所属站点标识。</param>
		/// <param name="specialCode">专题代码。</param>
		/// <returns>指定的专题标识。</returns>
		public static int? GetIdentifier(int siteId, string specialCode)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.Specials.GetIdentifier(siteId, specialCode);
		}
		#endregion




		#region GetItem
		/// <summary>
		/// 根据标识获取指定的专题。
		/// </summary>
		/// <param name="o">专题集合。</param>
		/// <param name="specialId">获取的专题标识 SpecialId。</param>
		/// <returns>获取的信息项。</returns>
		public static Special GetItem(this System.Data.Linq.Table<Special> o, int specialId)
		{
			return o.SingleOrDefault(p => p.SpecialId == specialId);
		}

		/// <summary>
		/// 根据标识获取指定的专题。
		/// </summary>
		/// <param name="specialId">获取的专题标识 SpecialId。</param>
		/// <returns>获取的信息项。</returns>
		public static Special GetItem(int specialId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.Specials.GetItem(specialId);
		}



		/// <summary>
		/// 根据标识获取指定的专题。
		/// </summary>
		/// <param name="o">专题集合。</param>
		/// <param name="siteId">所属站点标识。</param>
		/// <param name="specialCode">专题代码。</param>
		/// <returns>获取的信息项。</returns>
		public static Special GetItem(this System.Data.Linq.Table<Special> o, int siteId, string specialCode)
		{
			return o.SingleOrDefault(p => p.SiteId == siteId && p.SpecialCode == specialCode);
		}

		/// <summary>
		/// 根据标识获取指定的专题。
		/// </summary>
		/// <param name="siteId">所属站点标识。</param>
		/// <param name="specialCode">专题代码。</param>
		/// <returns>获取的信息项。</returns>
		public static Special GetItem(int siteId, string specialCode)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.Specials.GetItem(siteId, specialCode);
		}
		#endregion



		#region Exists
		/// <summary>
		/// 验证指定的专题是否已经存在。
		/// </summary>
		/// <param name="o">专题集合。</param>
		/// <param name="specialId">验证的专题标识 SpecialId。</param>
		/// <returns>布尔值表示指定的专题是否已经存在。</returns>
		public static bool Exists(this System.Data.Linq.Table<Special> o, int specialId)
		{
			return o.Any(p => p.SpecialId == specialId);
		}

		/// <summary>
		/// 验证指定的专题是否已经存在。
		/// </summary>
		/// <param name="specialId">验证的专题标识 SpecialId。</param>
		/// <returns>布尔值表示指定的专题是否已经存在。</returns>
		public static bool Exists(int specialId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.Specials.Exists(specialId);
		}




		/// <summary>
		/// 验证指定的专题是否已经存在。
		/// </summary>
		/// <param name="o">专题集合。</param>
		/// <param name="siteId">专题所属的站点。</param>
		/// <param name="classCode">专题的代码。</param>
		/// <returns>布尔值表示指定的专题是否已经存在。</returns>
		public static bool Exists(this System.Data.Linq.Table<Special> o, int siteId, string specialCode)
		{
			return o.Any(p => p.SiteId == siteId && p.SpecialCode == specialCode);
		}

		/// <summary>
		/// 验证指定的专题是否已经存在。
		/// </summary>
		/// <param name="siteId">专题所属的站点。</param>
		/// <param name="classCode">专题的代码。</param>
		/// <returns>布尔值表示指定的专题是否已经存在。</returns>
		public static bool Exists(int siteId, string specialCode)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.Specials.Exists(siteId, specialCode);
		}
		#endregion
	}



	/// <summary>
	/// Specials 类操作部分。
	/// </summary>
	public static partial class Specials
	{
		#region Insert
		/// <summary>
		/// 添加专题。
		/// </summary>
		/// <param name="insertedSpecial">添加的专题。</param>
		/// <returns>添加的专题。</returns>
		public static Special Insert(Special insertedSpecial)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Special special = insertedSpecial.ToNewEntity<Special>();
			special.IsEffective = false;
			special.IsRecommend = false;
			special.OrderNumber = 0;
			special.CreatorId = Users.CurrentUserId;
			special.CreationDate = DateTime.Now;

			GetInsertRight(dc, special, true);	// 权限验证

			dc.Specials.InsertOnSubmit(special);
			dc.SubmitChanges();

			// 持久化资源
			InfoItems.SetPersistent(dc, special.GlobalId, true);

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Insert, INFO_TYPE, special.SpecialId.ToString(), PermissionCode.Insert.ToString(), special.Title);

			// 返回只读数据
			return insertedSpecial.FillByEntity(special);
		}
		#endregion



		#region Update
		private static readonly HashSet<string> _updatedExcludeColumns = typeof(Special).GetEntityColumnNames(new string[] {
				"SpecialId",
				"SpecialCode",
				"CreatorId",
				"CreationDate",
				"IsEffective",
				"OrderNumber",
				"GlobalId",
				"SiteId",
				"MainNavigation",
				"IsRecommend"
			}, true);

		/// <summary>
		/// 修改专题。
		/// </summary>
		/// <param name="updatedSpecial">修改的专题。</param>
		/// <returns>修改的专题。</returns>
		public static Special Update(Special updatedSpecial)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Special special = dc.Specials.GetItem(updatedSpecial.SpecialId);
			if (special == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetUpdateRight(dc, special, true);	// 权限验证

			special.FillByEntity(updatedSpecial, EntityColumnsSetType.Exclude, _updatedExcludeColumns);

			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}

			// 持久化资源
			InfoItems.SetPersistent(dc, special.GlobalId, true);

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Update, INFO_TYPE, special.SpecialId.ToString(), PermissionCode.Update.ToString(), special.Title);

			// 返回只读数据
			return updatedSpecial.FillByEntity(special);
		}




		/// <summary>
		/// 更新主导航。
		/// </summary>
		/// <param name="specialId">更新的专题标识。</param>
		/// <param name="navs">导航列表。</param>
		public static void UpdateMainNavigation(int specialId, List<SpecialNavigationItem> navs)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Special special = dc.Specials.GetItem(specialId);
			if (special == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetUpdateRight(dc, special, true);	// 权限验证

			special.MainNavigationObject = navs;

			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Update, INFO_TYPE, special.SpecialId.ToString(), PermissionCode.Update.ToString() + "/MainNavigation", special.Title);
		}
		#endregion



		#region SetRolePermissionState
		/// <summary>
		/// 设置角色权限。
		/// </summary>
		/// <param name="settedSpecial">设置的专题。</param>
		/// <param name="roleName">设置的角色。</param>
		/// <param name="states">角色的状态。</param>
		public static void SetRolePermissions(Special settedSpecial, Guid roleId, IEnumerable<PermissionState> states)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Special special = dc.Specials.GetItem(settedSpecial.SpecialId);
			if (special == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetUpdateRight(dc, special, true);	// 权限验证

			Roles._SetRolePermissions(roleId, states);

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Update, INFO_TYPE, special.SpecialId.ToString(), PermissionCode.Update.ToString() + "/SetRolePermissions", special.Title);
		}
		#endregion



		#region Setting
		private static readonly HashSet<string> _settingColumns = typeof(Special).GetEntityColumnNames(new string[] {
				"IsEffective",
				"OrderNumber",
				"IsRecommend"
			}, true);

		/// <summary>
		/// 设置专题。
		/// </summary>
		/// <param name="settedSpecial">设置的专题。</param>
		/// <returns>设置的专题。</returns>
		public static Special Setting(Special settedSpecial)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Special special = dc.Specials.GetItem(settedSpecial.SpecialId);
			if (special == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetSettingRight(dc, special, true);	// 权限验证

			special.FillByEntity(settedSpecial, _settingColumns);

			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Setting, INFO_TYPE, special.SpecialId.ToString(), PermissionCode.Setting.ToString(), special.Title);

			// 返回只读数据
			return settedSpecial.FillByEntity(special);
		}
		#endregion



		#region SetEffectiveState
		/// <summary>
		/// 设置专题的有效状态。
		/// </summary>
		/// <param name="specialId">设置的专题标识 SpecialId。</param>
		public static void SetEffectiveState(int specialId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Special special = dc.Specials.GetItem(specialId);
			if (special == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetSetEffectiveStateRight(dc, special, true);	// 权限验证

			special.IsEffective = !special.IsEffective;
			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Setting, INFO_TYPE, special.SpecialId.ToString(), PermissionCode.Setting.ToString() + "/EffectiveState", special.Title);
		}

		/// <summary>
		/// 设置专题的推荐状态
		/// </summary>
		/// <param name="specialId"></param>
		public static void SetIsRecommendState(int specialId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Special special = dc.Specials.GetItem(specialId);
			if (special == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetSetEffectiveStateRight(dc, special, true);	// 权限验证

			special.IsRecommend = !special.IsRecommend;
			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Setting, INFO_TYPE, special.SpecialId.ToString(), PermissionCode.Setting.ToString() + "/SetIsRecommendState", special.Title);
		}


		/// <summary>
		/// 设置专题的有效状态。
		/// </summary>
		/// <param name="specialId">设置的专题标识 SpecialId。</param>
		/// <param name="state">设置的状态。</param>
		public static void SetEffectiveState(int specialId, bool state)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Special special = dc.Specials.GetItem(specialId);
			if (special == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetSetEffectiveStateRight(dc, special, true);	// 权限验证

			if (special.IsEffective == state)
				return;

			special.IsEffective = state;
			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Setting, INFO_TYPE, special.SpecialId.ToString(), PermissionCode.Setting.ToString() + "/EffectiveState", special.Title);
		}
		#endregion



		#region Delete
		/// <summary>
		/// 删除专题。
		/// </summary>
		/// <param name="specialId">删除的专题标识 SpecialId。</param>
		public static void Delete(int specialId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Special special = dc.Specials.GetItem(specialId);
			if (special == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetDeleteRight(dc, special, true);	// 权限验证

			Delete(dc, special);

			dc.SubmitChanges();

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Delete, INFO_TYPE, special.SpecialId.ToString(), PermissionCode.Delete.ToString(), special.Title);
		}

		#region internal Delete
		internal static void Delete(GenericModuleDataContext dc, Special special)
		{
			SpecialModules.DeleteByParent(dc, special);	// 删除关联数据
			SpecialPages.DeleteByParent(dc, special);	// 删除关联数据
			dc.Specials.DeleteOnSubmit(special);

			// 删除资源
			InfoItem infoItem = dc.InfoItems.GetItem(special.GlobalId);
			if (infoItem != null)
				InfoItems.Delete(dc, infoItem);
		}

		//internal static void DeleteByParent(GenericModuleDataContext dc, Site parent)
		//{
		//    IEnumerable<Special> e = parent.Specials.AsEnumerable();
		//    foreach (Special i in e)
		//        Delete(dc, i);
		//}
		#endregion
		#endregion
	}



	/// <summary>
	/// Specials 类对应操作权限部分。（受限站点资源。）
	/// </summary>
	public static partial class Specials
	{
		#region GetInsertRight
		/// <summary>
		/// 获取当前用户是否有添加专题的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="special">添加的专题对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有添加专题的权限。</returns>
		public static bool GetInsertRight(GenericModuleDataContext dc, Special special, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)PermissionCode.Insert;
			bool b = dc.AccessController.GetUserIsHasPermission<Special>(userName, special, ResourceId, permissionCode, special.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, special, ResourceId, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有添加专题的权限。
		/// </summary>
		/// <param name="special">添加的专题对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有添加专题的权限。</returns>
		public static bool GetInsertRight(Special special, bool triggerException)
		{
			return GetInsertRight(new GenericModuleDataContext(), special, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有添加专题的权限。
		/// </summary>
		/// <param name="special">添加的专题对象。</param>
		/// <returns>布尔值表示当前用户是否有添加专题的权限。</returns>
		public static bool GetInsertRight(Special special)
		{
			return GetInsertRight(special, false);
		}
		#endregion



		#region GetUpdateRight
		/// <summary>
		/// 获取当前用户是否有更新专题的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="special">更新的专题对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有更新专题的权限。</returns>
		public static bool GetUpdateRight(GenericModuleDataContext dc, Special special, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)PermissionCode.Update;
			bool b = dc.AccessController.GetUserIsHasPermission<Special>(userName, special, ResourceId, permissionCode, special.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, special, ResourceId, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有更新专题的权限。
		/// </summary>
		/// <param name="special">更新的专题对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有更新专题的权限。</returns>
		public static bool GetUpdateRight(Special special, bool triggerException)
		{
			return GetUpdateRight(new GenericModuleDataContext(), special, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有更新专题的权限。
		/// </summary>
		/// <param name="special">更新的专题对象。</param>
		/// <returns>布尔值表示当前用户是否有更新专题的权限。</returns>
		public static bool GetUpdateRight(Special special)
		{
			return GetUpdateRight(special, false);
		}
		#endregion



		#region GetSettingRight
		/// <summary>
		/// 获取当前用户是否有设置专题的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="special">设置的专题对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有设置专题的权限。</returns>
		public static bool GetSettingRight(GenericModuleDataContext dc, Special special, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)PermissionCode.Setting;
			bool b = dc.AccessController.GetUserIsHasPermission<Special>(userName, special, ResourceId, permissionCode, special.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, special, ResourceId, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有设置专题的权限。
		/// </summary>
		/// <param name="special">设置的专题对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有设置专题的权限。</returns>
		public static bool GetSettingRight(Special special, bool triggerException)
		{
			return GetSettingRight(new GenericModuleDataContext(), special, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有设置专题的权限。
		/// </summary>
		/// <param name="special">设置的专题对象。</param>
		/// <returns>布尔值表示当前用户是否有设置专题的权限。</returns>
		public static bool GetSettingRight(Special special)
		{
			return GetSettingRight(special, false);
		}



		public static bool GetSetEffectiveStateRight(GenericModuleDataContext dc, Special special, bool triggerException)
		{
			return GetSettingRight(dc, special, triggerException);
		}

		public static bool GetSetEffectiveStateRight(Special special, bool triggerException)
		{
			return GetSetEffectiveStateRight(new GenericModuleDataContext(), special, triggerException);
		}

		public static bool GetSetEffectiveStateRight(Special special)
		{
			return GetSetEffectiveStateRight(special, false);
		}
		#endregion



		#region GetDeleteRight
		/// <summary>
		/// 获取当前用户是否有删除专题的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="special">删除的专题对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有删除专题的权限。</returns>
		public static bool GetDeleteRight(GenericModuleDataContext dc, Special special, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)PermissionCode.Delete;
			bool b = dc.AccessController.GetUserIsHasPermission<Special>(userName, special, ResourceId, permissionCode, special.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, special, ResourceId, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有删除专题的权限。
		/// </summary>
		/// <param name="special">删除的专题对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有删除专题的权限。</returns>
		public static bool GetDeleteRight(Special special, bool triggerException)
		{
			return GetDeleteRight(new GenericModuleDataContext(), special, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有删除专题的权限。
		/// </summary>
		/// <param name="special">删除的专题对象。</param>
		/// <returns>布尔值表示当前用户是否有删除专题的权限。</returns>
		public static bool GetDeleteRight(Special special)
		{
			return GetDeleteRight(special, false);
		}
		#endregion
	}



	/// <summary>
	/// Specials 类后台管理部分。
	/// </summary>
	public static partial class Specials
	{
		public static bool GetManageListRight()
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			return dc.AccessController.GetUserIsHasPermission<object>(Users.CurrentUserName, null, Specials.ResourceId, (int)Specials.PermissionCode.Update, Sites.CurrentSiteId);
		}

		public static bool GetManageListRight(int? siteId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			return dc.AccessController.GetUserIsHasPermission<object>(Users.CurrentUserName, null, Specials.ResourceId, (int)Specials.PermissionCode.Update, siteId);
		}




		public struct SpecialForManageList
		{
			public int SpecialId { get; set; }
			public string SpecialCode { get; set; }
			public string ClassCode { get; set; }
			public string Title { get; set; }
			public string ViceTitle { get; set; }
			public string Keywords { get; set; }
			public int SiteId { get; set; }
			public DateTime CreationDate { get; set; }
			public bool IsEffective { get; set; }
			public bool IsRecommend { get; set; }
			public int OrderNumber { get; set; }
			public Guid? CreatorId { get; set; }
			public string ChannelIds { get; set; }
		}

		public static PaginationInfo<List<SpecialForManageList>> GetPaginationManageList(int? siteId, string classCode, string keyword, int pageSize, int currentPage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			var q = from p in dc.Specials
					orderby p.IsRecommend descending, p.OrderNumber descending, p.ReleaseDate descending, p.SpecialId descending
					select new SpecialForManageList
					{
						SpecialId = p.SpecialId,
						SpecialCode = p.SpecialCode,
						Title = p.Title,
						ViceTitle = p.ViceTitle,
						Keywords = p.Keywords,
						ClassCode = p.ClassCode,
						IsEffective = p.IsEffective,
						IsRecommend = p.IsRecommend,
						OrderNumber = p.OrderNumber,
						CreationDate = p.CreationDate,
						SiteId = p.SiteId,
						ChannelIds=p.ChannelIds
					};

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);

			if (!string.IsNullOrEmpty(classCode))
				q = q.Where(p => p.ClassCode == classCode);

			if (!string.IsNullOrEmpty(keyword))
			    q = q.Where(p => p.Title.Contains(keyword) || p.ViceTitle.Contains(keyword) || p.Keywords.Contains(keyword));

			PaginationInfo<List<SpecialForManageList>> pageInfo = new PaginationInfo<List<SpecialForManageList>>();
			pageInfo.PageSize = pageSize;
			pageInfo.CurrentPage = currentPage;
			pageInfo.RecordCount = q.Count();
			pageInfo.Records = q.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
			return pageInfo;
		}

		public static PaginationInfo<List<SpecialForManageList>> GetPaginationManageList(int? siteId, string classCode,int? channelId, string keyword, int pageSize, int currentPage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			var q = from p in dc.Specials
					orderby p.IsRecommend descending, p.OrderNumber descending, p.ReleaseDate descending, p.SpecialId descending
					select new SpecialForManageList
					{
						SpecialId = p.SpecialId,
						SpecialCode = p.SpecialCode,
						Title = p.Title,
						ViceTitle = p.ViceTitle,
						Keywords = p.Keywords,
						ClassCode = p.ClassCode,
						IsEffective = p.IsEffective,
						IsRecommend = p.IsRecommend,
						OrderNumber = p.OrderNumber,
						CreationDate = p.CreationDate,
						SiteId = p.SiteId,
						ChannelIds = p.ChannelIds
					};

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);

			if (channelId.HasValue)
			{
				string channels = Dictionaries.BuildDicCombineValues<int>(channelId.Value);
				q = q.Where(p => p.ChannelIds.Contains(channels));
			}

			if (!string.IsNullOrEmpty(classCode))
				q = q.Where(p => p.ClassCode == classCode);

			if (!string.IsNullOrEmpty(keyword))
				q = q.Where(p => p.Title.Contains(keyword) || p.ViceTitle.Contains(keyword) || p.Keywords.Contains(keyword));

			PaginationInfo<List<SpecialForManageList>> pageInfo = new PaginationInfo<List<SpecialForManageList>>();
			pageInfo.PageSize = pageSize;
			pageInfo.CurrentPage = currentPage;
			pageInfo.RecordCount = q.Count();
			pageInfo.Records = q.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
			return pageInfo;
		}
	}




	/// <summary>
	/// Specials 类前台显示部分。
	/// </summary>
	public static partial class Specials
	{
		public struct SpecialForClientSummaryList
		{
			public int SpecialId { get; set; }
			public string SpecialCode { get; set; }
			public string ClassCode { get; set; }
			public string Title { get; set; }
			public string ViceTitle { get; set; }
			public string Keywords { get; set; }
			public bool IsRecommend { get; set; }
			public string Image { get; set; }
			public string Summary { get; set; }
			public string LinkUrl { get; set; }
			public int SiteId { get; set; }
			public DateTime ReleaseDate { get; set; }
			public int OrderNumber { get; set; }
			public string ChannelIds { get; set; }
		}

		private static IQueryable<SpecialForClientSummaryList> GetSummaryListQuery(GenericModuleDataContext dc, int? siteId, string classCode, string keyword)
		{
			var q = from p in dc.Specials
					where p.IsEffective == true
					orderby p.IsRecommend descending, p.OrderNumber descending, p.ReleaseDate descending, p.SpecialId descending
					select new SpecialForClientSummaryList
					{
						SpecialId = p.SpecialId,
						SpecialCode = p.SpecialCode,
						ClassCode = p.ClassCode,
						Title = p.Title,
						ViceTitle = p.ViceTitle,
						Keywords = p.Keywords,
						Image = p.Image,
						Summary = p.Summary,
						LinkUrl = p.LinkUrl,
						ReleaseDate = p.ReleaseDate,
						IsRecommend = p.IsRecommend,
						SiteId = p.SiteId,
						OrderNumber = p.OrderNumber,
						ChannelIds = p.ChannelIds
					};

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);

			if (!string.IsNullOrEmpty(classCode))
				q = q.Where(p => p.ClassCode == classCode);

			if (!string.IsNullOrEmpty(keyword))
				q = q.Where(p => p.Title.Contains(keyword) || p.ViceTitle.Contains(keyword) || p.Keywords.Contains(keyword));

			return q;
		}		
		public static PaginationInfo<List<SpecialForClientSummaryList>> GetPaginationSummaryList(int? siteId, string classCode, string keyword, int pageSize, int currentPage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientSummaryList> q = GetSummaryListQuery(dc, siteId, classCode, keyword);

			PaginationInfo<List<SpecialForClientSummaryList>> pageInfo = new PaginationInfo<List<SpecialForClientSummaryList>>();
			pageInfo.PageSize = pageSize;
			pageInfo.CurrentPage = currentPage;
			pageInfo.RecordCount = q.Count();
			pageInfo.Records = q.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
			return pageInfo;
		}
		public static List<SpecialForClientSummaryList> GetSummaryList(int? siteId, string classCode, string keyword, int? loadCount)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientSummaryList> q = GetSummaryListQuery(dc, siteId, classCode, keyword);

			if (loadCount.HasValue)
				return q.Take(loadCount.Value).ToList();
			return q.ToList();
		}
		public static List<SpecialForClientSummaryList> GetSummaryList(int? siteId, string classCode, string[] classCodes,string keyword, int? loadCount)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientSummaryList> q = GetSummaryListQuery(dc, siteId, classCode, keyword);

			var q2 = q.ToList();

			if (classCodes.Count() > 0)
			{
				q2 = classCodes.SelectMany(c => q.Where(p => p.ClassCode == c)).ToList();
			}
			q2 = q2.OrderByDescending(p => p.IsRecommend).OrderByDescending(p => p.OrderNumber).OrderByDescending(p => p.ReleaseDate).ToList();
			if (loadCount.HasValue)
				return q2.Take(loadCount.Value).ToList();
			return q2.ToList();
		}
		
		private static IQueryable<SpecialForClientSummaryList> GetSummaryListQuery(GenericModuleDataContext dc, int? siteId, string classCode, int? channelId, string keyword)
		{
			var q = from p in dc.Specials
					where p.IsEffective == true
					orderby p.IsRecommend descending, p.OrderNumber descending, p.ReleaseDate descending, p.SpecialId descending
					select new SpecialForClientSummaryList
					{
						SpecialId = p.SpecialId,
						SpecialCode = p.SpecialCode,
						ClassCode = p.ClassCode,
						Title = p.Title,
						ViceTitle = p.ViceTitle,
						Keywords = p.Keywords,
						Image = p.Image,
						Summary = p.Summary,
						LinkUrl = p.LinkUrl,
						ReleaseDate = p.ReleaseDate,
						IsRecommend = p.IsRecommend,
						SiteId = p.SiteId,
						OrderNumber = p.OrderNumber,
						ChannelIds = p.ChannelIds
					};

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);

			if (channelId.HasValue)
			{
				string channels = Dictionaries.BuildDicCombineValues<int>(channelId.Value);
				q = q.Where(p => p.ChannelIds.Contains(channels));
			}

			if (!string.IsNullOrEmpty(classCode))
				q = q.Where(p => p.ClassCode == classCode);

			if (!string.IsNullOrEmpty(keyword))
				q = q.Where(p => p.Title.Contains(keyword) || p.ViceTitle.Contains(keyword) || p.Keywords.Contains(keyword));

			return q;
		}
		public static PaginationInfo<List<SpecialForClientSummaryList>> GetPaginationSummaryList(int? siteId, int? channelId, string classCode, string keyword, int pageSize, int currentPage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientSummaryList> q = GetSummaryListQuery(dc, siteId, classCode,channelId, keyword);

			PaginationInfo<List<SpecialForClientSummaryList>> pageInfo = new PaginationInfo<List<SpecialForClientSummaryList>>();
			pageInfo.PageSize = pageSize;
			pageInfo.CurrentPage = currentPage;
			pageInfo.RecordCount = q.Count();
			pageInfo.Records = q.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
			return pageInfo;
		}
		public static List<SpecialForClientSummaryList> GetSummaryList(int? siteId, int? channelId, string classCode, string keyword, int? loadCount)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientSummaryList> q = GetSummaryListQuery(dc, siteId, classCode, channelId, keyword);

			if (loadCount.HasValue)
				return q.Take(loadCount.Value).ToList();
			return q.ToList();
		}
		public static List<SpecialForClientSummaryList> GetSummaryList(int? siteId, int? channelId, string classCode, string[] classCodes, string keyword, int? loadCount)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientSummaryList> q = GetSummaryListQuery(dc, siteId, classCode, channelId, keyword);

			var q2 = q.ToList();

			if (classCodes.Count() > 0)
			{
				q2 = classCodes.SelectMany(c => q.Where(p => p.ClassCode == c)).ToList();
			}
			q2 = q2.OrderByDescending(p => p.IsRecommend).OrderByDescending(p => p.OrderNumber).OrderByDescending(p => p.ReleaseDate).ToList();
			if (loadCount.HasValue)
				return q2.Take(loadCount.Value).ToList();
			return q2.ToList();
		}
		
		public struct SpecialForClientBaseList
		{
			public int SpecialId { get; set; }
			public string SpecialCode { get; set; }
			public string ClassCode { get; set; }
			public string Title { get; set; }
			public string ViceTitle { get; set; }
			public string Keywords { get; set; }
			public string Image { get; set; }
			public bool IsRecommend { get; set; }
			public string LinkUrl { get; set; }
			public int SiteId { get; set; }
			public DateTime ReleaseDate { get; set; }
			public Guid? CreatorId { get; set; }
			public int OrderNumber { get; set; }
			public string ChannelIds { get; set; }
		}

		private static IQueryable<SpecialForClientBaseList> GetBaseListQuery(GenericModuleDataContext dc, int? siteId, string classCode, string keyword)
		{
			var q = from p in dc.Specials
					where p.IsEffective == true
					orderby p.IsRecommend descending, p.OrderNumber descending, p.ReleaseDate descending, p.SpecialId descending
					select new SpecialForClientBaseList
					{
						SpecialId = p.SpecialId,
						SpecialCode = p.SpecialCode,
						ClassCode = p.ClassCode,
						Title = p.Title,
						ViceTitle = p.ViceTitle,
						Keywords = p.Keywords,
						Image = p.Image,
						LinkUrl = p.LinkUrl,
						ReleaseDate = p.ReleaseDate,
						IsRecommend = p.IsRecommend,
						SiteId = p.SiteId,
						OrderNumber = p.OrderNumber,
						ChannelIds = p.ChannelIds
					};

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);

			if (!string.IsNullOrEmpty(classCode))
				q = q.Where(p => p.ClassCode == classCode);

			if (!string.IsNullOrEmpty(keyword))
				q = q.Where(p => p.Title.Contains(keyword) || p.ViceTitle.Contains(keyword) || p.Keywords.Contains(keyword));

			return q;
		}

		public static PaginationInfo<List<SpecialForClientBaseList>> GetPaginationBaseList(int? siteId, string classCode, string keyword, int pageSize, int currentPage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientBaseList> q = GetBaseListQuery(dc, siteId, classCode, keyword);

			PaginationInfo<List<SpecialForClientBaseList>> pageInfo = new PaginationInfo<List<SpecialForClientBaseList>>();
			pageInfo.PageSize = pageSize;
			pageInfo.CurrentPage = currentPage;
			pageInfo.RecordCount = q.Count();
			pageInfo.Records = q.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
			return pageInfo;
		}

		public static List<SpecialForClientBaseList> GetBaseList(int? siteId, string classCode, string keyword, int? loadCount)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientBaseList> q = GetBaseListQuery(dc, siteId, classCode, keyword);

			if (loadCount.HasValue)
				return q.Take(loadCount.Value).ToList();
			return q.ToList();
		}

		
		public static List<SpecialForClientBaseList> GetBaseList(int? siteId, string classCode, string[] classCodes,  string keyword, int? loadCount)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientBaseList> q = GetBaseListQuery(dc, siteId, classCode, keyword);

			var q2 = q.ToList();
			
			if (classCodes.Count() > 0)
			{
				q2 = classCodes.SelectMany(c => q.Where(p => p.ClassCode == c)).ToList();
			}

			q2 = q2.OrderByDescending(p => p.IsRecommend).OrderByDescending(p => p.OrderNumber).OrderByDescending(p => p.ReleaseDate).ToList();

			if (loadCount.HasValue)
				return q2.Take(loadCount.Value).ToList();
			return q2.ToList();
		}

		private static IQueryable<SpecialForClientBaseList> GetBaseListQuery(GenericModuleDataContext dc,int? siteId, Guid? userId, DateTime? startDate,DateTime? endDate)
		{
			var q = from p in dc.Specials
					where p.IsEffective == true
					orderby p.IsRecommend descending, p.OrderNumber descending, p.ReleaseDate descending, p.SpecialId descending
					select new SpecialForClientBaseList
					{
						SpecialId = p.SpecialId,
						SpecialCode = p.SpecialCode,
						ClassCode = p.ClassCode,
						Title = p.Title,
						ViceTitle = p.ViceTitle,
						Keywords = p.Keywords,
						Image = p.Image,
						LinkUrl = p.LinkUrl,
						ReleaseDate = p.ReleaseDate,
						IsRecommend = p.IsRecommend,
						SiteId = p.SiteId,
						CreatorId = p.CreatorId,
						ChannelIds = p.ChannelIds
					};
			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);

			if (userId.HasValue)
				q = q.Where(p => p.CreatorId.Value== userId.Value);

			if (startDate.HasValue)
				q = q.Where(p => p.ReleaseDate >= startDate.Value);

			if (endDate.HasValue)
				q = q.Where(p => p.ReleaseDate <= endDate.Value);

			return q;
		}

		public static List<SpecialForClientBaseList> GetBaseList(int? siteId,Guid? userId, DateTime? startDate, DateTime? endDate)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientBaseList> q = GetBaseListQuery(dc, siteId, userId, startDate, endDate);
			
			return q.ToList();
		}


		private static IQueryable<SpecialForClientBaseList> GetBaseListQuery(GenericModuleDataContext dc, int? siteId, string classCode, string keyword, int? channelId)
		{
			var q = from p in dc.Specials
					where p.IsEffective == true
					orderby p.IsRecommend descending, p.OrderNumber descending, p.ReleaseDate descending, p.SpecialId descending
					select new SpecialForClientBaseList
					{
						SpecialId = p.SpecialId,
						SpecialCode = p.SpecialCode,
						ClassCode = p.ClassCode,
						Title = p.Title,
						ViceTitle = p.ViceTitle,
						Keywords = p.Keywords,
						Image = p.Image,
						LinkUrl = p.LinkUrl,
						ReleaseDate = p.ReleaseDate,
						IsRecommend = p.IsRecommend,
						SiteId = p.SiteId,
						OrderNumber = p.OrderNumber,
						ChannelIds = p.ChannelIds
					};

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);

			if (channelId.HasValue)
			{
				string channels = Dictionaries.BuildDicCombineValues<int>(channelId.Value);
				q = q.Where(p => p.ChannelIds.Contains(channels));
			}

			if (!string.IsNullOrEmpty(classCode))
				q = q.Where(p => p.ClassCode == classCode);

			if (!string.IsNullOrEmpty(keyword))
				q = q.Where(p => p.Title.Contains(keyword) || p.ViceTitle.Contains(keyword) || p.Keywords.Contains(keyword));

			return q;
		}

		public static List<SpecialForClientBaseList> GetBaseList(int? siteId, string classCode, string[] classCodes, string keyword, int? loadCount, int? channelId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientBaseList> q = GetBaseListQuery(dc, siteId, classCode, keyword, channelId);

			var q2 = q.ToList();

			if (classCodes.Count() > 0)
			{
				q2 = classCodes.SelectMany(c => q.Where(p => p.ClassCode == c)).ToList();
			}

			q2 = q2.OrderByDescending(p => p.IsRecommend).OrderByDescending(p => p.OrderNumber).OrderByDescending(p => p.ReleaseDate).ToList();

			if (loadCount.HasValue)
				return q2.Take(loadCount.Value).ToList();
			return q2.ToList();
		}

		private static IQueryable<SpecialForClientBaseList> GetBaseListQuery(GenericModuleDataContext dc, int? siteId, Guid? userId, DateTime? startDate, DateTime? endDate, int? channelId)
		{
			var q = from p in dc.Specials
					where p.IsEffective == true
					orderby p.IsRecommend descending, p.OrderNumber descending, p.ReleaseDate descending, p.SpecialId descending
					select new SpecialForClientBaseList
					{
						SpecialId = p.SpecialId,
						SpecialCode = p.SpecialCode,
						ClassCode = p.ClassCode,
						Title = p.Title,
						ViceTitle = p.ViceTitle,
						Keywords = p.Keywords,
						Image = p.Image,
						LinkUrl = p.LinkUrl,
						ReleaseDate = p.ReleaseDate,
						IsRecommend = p.IsRecommend,
						SiteId = p.SiteId,
						CreatorId = p.CreatorId,
						ChannelIds = p.ChannelIds
					};
			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);

			if (channelId.HasValue)
			{
				string channels = Dictionaries.BuildDicCombineValues<int>(channelId.Value);
				q = q.Where(p => p.ChannelIds.Contains(channels));
			}

			if (userId.HasValue)
				q = q.Where(p => p.CreatorId.Value == userId.Value);

			if (startDate.HasValue)
				q = q.Where(p => p.ReleaseDate >= startDate.Value);

			if (endDate.HasValue)
				q = q.Where(p => p.ReleaseDate <= endDate.Value);

			return q;
		}

		public static List<SpecialForClientBaseList> GetBaseList(int? siteId, Guid? userId, DateTime? startDate, DateTime? endDate, int? channelId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<SpecialForClientBaseList> q = GetBaseListQuery(dc, siteId, userId, startDate, endDate, channelId);

			return q.ToList();
		}
	}
}